<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0046)http://www.vovisoft.com/dotNET/Bai11/Bai11.htm -->
<HTML><HEAD><TITLE>.NET Lesson 11</TITLE>
<META http-equiv=Content-Type content="text/html; charset=utf-8">
<META http-equiv=Content-Language content=vi>
<META content="MSHTML 5.50.4134.100" name=GENERATOR>
<META content=FrontPage.Editor.Document name=ProgId>
<META 
content="Visual Basic, VB Programming in Vietnamese, Vovisoft, VB6, VB Tutorials, Learn Visual Basic, Internet, Unicode, Vietnamese VB tutorials, Database, Asp, Java, Javascript, VBscript, FrontPage 2000, XML, Ms Office 2000" 
name=keywords></HEAD>
<BODY leftMargin=0 topMargin=0 marginheight="0" marginwidth="0">
<CENTER><A href="http://www.vovisoft.com/"><IMG alt="Logo of Vovisoft" 
src="Bai 11_files/vs-logo4_10.gif" border=0> </A><FONT face=Tahoma>
<H2><FONT face=Tahoma color=#800000>Bài 11</FONT></H2>
<H2><FONT face=Tahoma color=#800000>Những chức năng mới trong giao diện cửa sổ 
của VB.NET (phần IV)</FONT></H2></CENTER>
<BLOCKQUOTE>
  <BLOCKQUOTE>
    <H3><FONT color=green>Các control Providers</FONT></H3>Trong Windows Forms 
    có một gia đình controls mới mà ta chỉ có thể dùng khi chúng đi chung với 
    các controls khác trên cùng một form. Chúng được gọi là <B>Provider 
    Controls</B> và có đặc tính là khiến cho các property mới hiện ra trong các 
    controls khác.<BR><BR>Provider Controls không hiển thị trên form lúc chạy 
    program. Do đó chúng nằm riêng trong Component Tray lúc ta thiết kế. Hiện 
    giờ có 3 Provider Controls : <B>HelpProvider, ToolTip</B> và 
    <B>ErrorProvider</B>. Cả ba đều làm việc một cách tương tự nhau. 
    <H3><FONT color=blue>Controls HelpProvider và ToolTip</FONT></H3>Trong VB6, 
    các controls có <B>property HelpContextID</B> để ta chỉ định khi user bấm 
    nút <B>F1</B> thì chương trình sẽ hiển thị Help ở đúng trang có trị số 
    HelpContextID trong Help file. Còn <B>ToolTip</B> là một Textstring property 
    của mỗi control. Ta chỉ cần dùng cửa sổ Properties để cho vào ToolTip text 
    của một control là trong lúc chạy chương trình, khi nào ta để mouse cursor 
    nằm lên control là chương trình sẽ hiển thị ToolTip text.<BR><BR>Hai thứ ấy 
    không còn dùng trong Windows Forms nữa. Thay vào đó, ta phải đặt các 
    Provider Controls lên form để thực hiện các công tác tương 
    đương.<BR><BR><B>Control HelpProvider</B> cho phép các controls khác chỉ 
    định context sensitive help (trợ giúp trong tình huống đương thời) hiển thị 
    khi user bấm nút <B>F1</B>. Khi một control HelpProvider (gọi là 
    HelProvider1 by default) được thêm vào một form, thì mọi controls trên form 
    đều sẽ có thêm các properties dưới đây, chúng sẽ hiển thị trong cửa sổ 
    Properties sau khi ta chọn một control.<BR><BR>
    <TABLE cellSpacing=5 cellPadding=5 border=2>
      <TBODY>
      <TR>
        <TD align=middle><B><FONT color=blue>Property</FONT></B></TD>
        <TD align=middle><B><FONT color=blue>Áp dụng</FONT></B></TD></TR>
      <TR>
        <TD><B>HelpString on HelpProvider1</B></TD>
        <TD>Khi control được focus, user bấm nút F1 sẽ popup Tooltip 
          HelpString cho control</TD></TR>
      <TR>
        <TD><B>HelpTopic on HelpProvider1</B></TD>
        <TD>Cung cấp một Topic cho control để dùng trong Help file cho 
          context-sensitive help. Control HelpProvider1 có một property để ta 
          chỉ định dùng Help file nào</TD></TR>
      <TR>
        <TD><B>ShowHelp on HelpProvider1</B></TD>
        <TD>Xác định là control HelpProvider có <B>Active</B> cho control nầy 
          không</TD></TR></TBODY></TABLE><BR>Một khi <B>property HelpString</B> đã 
    được cho một Textstring thì trong lúc control nhận được focus, nếu user bấm 
    nút F1 một Tooltip sẽ hiển thị Textstring ấy. HelpProvider có một property 
    để dẫn đến một Help file, hoặc là HTMLHelp file, hoặc là Win32Help file, và 
    trị số trong <B>property HelpTopic</B> sẽ chỉ dẫn đến topic ấy trong Help 
    file.<BR><BR>
    <BLOCKQUOTE><IMG src="Bai 11_files/HelpToolTip.gif"></BLOCKQUOTE>Trong lúc 
    chương trình chạy, ta cũng có thể thay đổi trị số HelpString của 
    <B>Textbox1</B> như sau:<BR>
    <BLOCKQUOTE>
      <TABLE bgColor=#f6f6f6>
        <TBODY>
        <TR>
          <TD><FONT size=3><PRE>HelpProvider1.SetHelpString(Textbox1, "Một HelpString mới được dùng tại đây.") 
</PRE></FONT></TD></TR></TBODY></TABLE></BLOCKQUOTE><B>Control ToolTip</B> 
    cũng hoạt động tương tự, nhưng đơn giản hơn. Nó chỉ cho thêm một property 
    mới tên <B>ToolTip on ToolTip1</B> vào mỗi control, giả dụ tên của ToopTip 
    provider là ToolTip1. Property nầy làm việc y hệt như ToolTipText trong 
    VB6.<BR><BR>Trong lúc chương trình chạy, ta cũng có thể set cho property 
    Tooltip của Textbox <B>txtName</B> một trị số Textstring như sau:<BR>
    <BLOCKQUOTE>
      <TABLE bgColor=#f6f6f6>
        <TBODY>
        <TR>
          <TD><FONT size=3><PRE>ToolTip1.SetToolTip(txtName, "Xin vui lòng đánh tên bạn vào đây") 
</PRE></FONT></TD></TR></TBODY></TABLE></BLOCKQUOTE>
    <H3><FONT color=blue>Control ErrorProvider</FONT></H3>Thông thường sau khi 
    user điền xong các dữ kiện vào một form thì sẽ click một button <B>OK</B> 
    hay <B>Submit</B> chẳng hạn. Để tránh trường hợp cập nhật data của một 
    record với những dữ kiện bất hợp lệ, ta thường kiểm tra lại dữ kiện nằm 
    trong từng Textbox trên form và hiển thị một thông điệp để nhắc nhở và giải 
    thích cho user khi có error. Nếu user lầm lỗi ở nhiều Textboxes thì có thể 
    sẽ có nhiều thông điệp hiển thị lần lượt cái nầy tiếp theo cái kia, mỗi 
    thông điệp liên hệ đến một Textbox có error. Cách ấy cũng tạm được, nhưng có 
    thể khiến cho user bực mình.<BR><BR><B>Control ErrorProvider</B> cung cấp 
    một cách đơn giản và thân thiện để cho user biết Textbox nào có dữ kiện bất 
    hợp lệ. Control ErrorProvider cho các controls trên cùng form một property 
    mới gọi là <B>Error on ErrorProvider1</B> ( giả dụ là control ErrorProvider 
    mang tên ErrorProvider1).<BR><BR>Trong lúc chương trình chạy, nếu kiểm thấy 
    một Textbox có lỗi ta assign một TextString vào property Error on 
    ErrorProvider1 của Textbox ấy. Lúc bấy giờ một icon đỏ hình dấu chấm than 
    trắng sẽ hiển thị bên phải Textbox có Error. Nếu user để mouse cursor lên 
    trên icon ấy thì chương trình sẽ hiển thị một Tooltip với trị số TextString 
    của property Error on ErrorProvider1 giống như trong hình dưới đây:<BR><BR>
    <BLOCKQUOTE><IMG src="Bai 11_files/ErrorToolTip.gif"></BLOCKQUOTE>Công việc 
    assign một TextString vào property Error on ErrorProvider1 của một Textbox 
    có thể được coded như sau:<BR><BR>
    <BLOCKQUOTE>
      <TABLE bgColor=#f6f6f6>
        <TBODY>
        <TR>
          <TD><FONT size=3><PRE><FONT color=blue>Private</FONT> <FONT color=blue>Sub</FONT> BtnOK_Click( <FONT color=blue>ByVal</FONT> sender <FONT color=blue>As</FONT> System.Object, <FONT color=blue>ByVal</FONT> e <FONT color=blue>As</FONT> System.EventArgs) <FONT color=blue>Handles</FONT> BtnOK.Click 
  <FONT color=green>' Set error if TextBox txtName is blank</FONT>
   <FONT color=blue>If</FONT> txtName.Text = "" <FONT color=blue>Then</FONT> 
     <FONT color=green>' Assign error ToolTip message to Textbox txtName</FONT>
      ErrorProvider1.SetError(txtName, "You must supply a name!") 
   <FONT color=blue>End</FONT> <FONT color=blue>If</FONT> 
<FONT color=blue>End</FONT> <FONT color=blue>Sub</FONT> 
</PRE></FONT></TD></TR></TBODY></TABLE></BLOCKQUOTE>Trên đây ta dùng Event 
    Click của button BtnOK để kiểm tra dữ kiện trong mọi Textbox. Có một Event 
    của các controls mà ta cũng có thể dùng trong công tác kiểm tra dữ kiện của 
    một TextBox. Đó là <B>Event Validating</B>. Để gây ra Event Validating ta 
    cần phải dùng <B>property CauseValidation</B> của các controls. Thông 
    thường, property CauseValidation của các controls được set thành True. 
    TextBox txtName chỉ tạo ra Event Validating khi chính property 
    CauseValidation của nó là True và khi focus được di chuyển đến một control 
    khác có property CauseValidation là True.<BR><BR>Xin lưu ý là không nhất 
    thiết Event Validating được tạo ra khi txtName mất focus. Khi txtName mất 
    focus thì Textbox txtAge được focus (giả dụ txtAge có trị số TabOrder ngay 
    sau txtName) , nhưng nếu property CauseValidation của txtAge không phải là 
    True thì phải đợi đến khi focus đáp lên một control có property 
    CauseValidation là True txtName mới gây ra Event Validating.<BR><BR>Ta có 
    thể code cho <B>Sub txtName_Validating</B> như sau:<BR><BR>
    <TABLE bgColor=#f6f6f6>
      <TBODY>
      <TR>
        <TD><FONT size=3><PRE><FONT color=blue>Private</FONT> <FONT color=blue>Sub</FONT> txtName_Validating( <FONT color=blue>ByVal</FONT> sender <FONT color=blue>As</FONT> Object, <FONT color=blue>ByVal</FONT> e <FONT color=blue>As</FONT> System.ComponentModel.CancelEventArgs)  _
                                                           <FONT color=blue>Handles</FONT> txtName.Validating 
  <FONT color=green>' Set error if TextBox txtName is blank</FONT>
   <FONT color=blue>If</FONT> txtName.Text = "" <FONT color=blue>Then</FONT> 
     <FONT color=green>' Assign error ToolTip message to Textbox txtName</FONT>
      ErrorProvider1.SetError(txtName, "You must supply a name!") 
   <FONT color=blue>Else</FONT> 
     <FONT color=green>' Clear the error ToolTip message for Textbox txtName and make error Icon invisible</FONT>
      ErrorProvider1.SetError(txtName, "") 
   <FONT color=blue>End</FONT> <FONT color=blue>If</FONT> 
<FONT color=blue>End</FONT> <FONT color=blue>Sub</FONT> 
</PRE></FONT></TD></TR></TBODY></TABLE>Cái icon đỏ hình dấu chấm than trắng 
    là <B>default icon</B> của ErrorProvider. Muốn dùng một icon khác ta chỉ cần 
    assign icon ấy vào <B>property Icon</B> của ErrorProvider. 
    <H3><FONT color=green>Menus</FONT></H3>Mặc dầu <B>Menu Editor</B> của VB6 
    cung cấp đầy đủ các phương tiện để làm Menu và tương đối dễ dùng, VB.NET cho 
    ta một giao diện càng thân thiện và tự nhiên hơn để thiết kế Menu. 
    <BR><BR>Menu được thêm vào form dưới dạng một control. Tuy Menu control nằm 
    trong một mâm components phía dưới, nhưng trong lúc thiết kế, Menu hiện ra 
    trong form y như lúc Runtime và bạn chỉ cần điền vào các menuitems cần 
    thiết. Có hai loại menus: Main Menu (Menu dùng thông thường) và Context Menu 
    (dùng cho Pop-Up). <BR><BR>Bạn có thể <A 
    href="http://www.vovisoft.com/dotNET/Bai11/ErrorProvider.zip">tải về chương 
    trình ErrorProvider nầy</A> tại đây. 
    <H3><FONT color=blue>Menus</FONT></H3>Main Menu là Menu căn bản mà bạn thấy 
    nó dính vào cạnh trên của một form. Để dễ giải thích, ta sẽ dùng một thí dụ 
    tạo ra một Editor thật đơn giản bằng VB.NET. Bạn hãy khởi động một Windows 
    Application mới và thêm một Textbox vào trong form chính. Set <B>property 
    MultiLine </B>của Textbox thành True để nó có thể hiển thị nhiều hàng, đồng 
    thời Stretch (kéo dãn ra) cái Textbox cho lớn ra làm nơi ta có thể đánh vào 
    một bài text. <BR><BR>Kế đó, thêm một Main Menu vào form. Cái menu Designer 
    sẽ kích động và bạn chỉ cần đánh vào chi tiết các menuItems và dùng cửa sổ 
    Properties để set các parameters.<BR><BR>Khi nào bạn select control Main 
    Menu trong mâm components là bạn có thể edit các MenuItems. Muốn làm việc 
    với MenuItem nào thì select MenuItem đó. Những chỗ có chữ <B>Type Here</B> 
    là đề nghị cho bạn đánh thêm vào một MenuItem (<B>Type Here</B> nằm phía 
    dưới) , một MenuCommand mới (<B>Type Here</B> nằm bên phải một MenuCommand) 
    hay một MenuSubItem (<B>Type Here</B> nằm bên phải một MenuItem).<BR><BR>
    <BLOCKQUOTE><IMG src="Bai 11_files/DesignMenu.gif"></BLOCKQUOTE>Muốn insert 
    một lằn ngang giữa MenuItem <B>Paste</B> và MenuItem <B>Clear All</B>, bạn 
    select MenuItem Clear All rồi right click và chọn <B>Insert Separator</B> 
    trong Pop-Up Menu. 
    <BLOCKQUOTE><IMG src="Bai 11_files/Separator.gif"></BLOCKQUOTE>Muốn chỉ định 
    Shortcut cho một MenuItem, bạn select MenuItem ấy rồi vào cửa sổ Properties 
    để chọn trị số cho <B>property Shortcut</B>. Tương tự như vậy cho 
    <B>property Checked</B> để làm một checkmark hiện ra bên trái (phía trước) 
    Text của MenuItem. 
    <BLOCKQUOTE><IMG src="Bai 11_files/Shortcut.gif"></BLOCKQUOTE>Thêm vào các 
    dòng code sau đây cho chương trình. Khi doubleClick lên MenuItem 
    <B>copyMenuItem</B> cửa sổ mã nguồn sẽ mở ra cho bạn đánh code cho 
    <B>Private Sub copyMenuItem_Click</B>:<BR><BR>
    <TABLE bgColor=#f6f6f6>
      <TBODY>
      <TR>
        <TD><FONT size=3><PRE><FONT color=blue>Private</FONT> <FONT color=blue>Sub</FONT> copyMenuItem_Click( <FONT color=blue>ByVal</FONT> sender <FONT color=blue>As</FONT> System.Object, <FONT color=blue>ByVal</FONT> e <FONT color=blue>As</FONT> System.EventArgs) 
                                  <FONT color=blue>Handles</FONT> copyMenuItem.Click 
  <FONT color=green>' Copy the selected text to the Clipboard</FONT>
   Textbox1.Copy() 
<FONT color=blue>End</FONT> <FONT color=blue>Sub</FONT> 

<FONT color=blue>Private</FONT> <FONT color=blue>Sub</FONT> pasteMenuItem_Click( <FONT color=blue>ByVal</FONT> sender <FONT color=blue>As</FONT> System.Object, <FONT color=blue>ByVal</FONT> e <FONT color=blue>As</FONT> System.EventArgs) 
                                  <FONT color=blue>Handles</FONT> pasteMenuItem.Click 
  <FONT color=green>'Paste the Clipboard text into Textbox1</FONT>
   Textbox1.Paste() 
<FONT color=blue>End</FONT> <FONT color=blue>Sub</FONT> 

<FONT color=blue>Private</FONT> <FONT color=blue>Sub</FONT> clearAllMenuItem_Click( <FONT color=blue>ByVal</FONT> sender <FONT color=blue>As</FONT> System.Object, <FONT color=blue>ByVal</FONT> e <FONT color=blue>As</FONT> System.EventArgs) 
                                  <FONT color=blue>Handles</FONT> clearAllMenuItem.Click 
  <FONT color=green>' Clear everything in Textbox1</FONT>
   Textbox1.Text = "" 
<FONT color=blue>End</FONT> <FONT color=blue>Sub</FONT> 

<FONT color=blue>Private</FONT> <FONT color=blue>Sub</FONT> closeMenuItem_Click( <FONT color=blue>ByVal</FONT> sender <FONT color=blue>As</FONT> System.Object, <FONT color=blue>ByVal</FONT> e <FONT color=blue>As</FONT> System.EventArgs) 
                                  <FONT color=blue>Handles</FONT> closeMenuItem.Click 
  <FONT color=green>' Close the form</FONT>
   Me.Close() 
<FONT color=blue>End</FONT> <FONT color=blue>Sub</FONT> 
</PRE></FONT></TD></TR></TBODY></TABLE>Khi chạy chương trình, hình dưới đây 
    sẽ hiển thị:<BR><BR>
    <BLOCKQUOTE><IMG src="Bai 11_files/Editor.gif"></BLOCKQUOTE>
    <H3><FONT color=blue>Context Menus</FONT></H3>Ta dùng Context Menu để Pop-Up 
    một Menu xứng hợp với tình huống đương thời của program khi user right click 
    một control trên form. Trong VB6, Context Menu cũng là một MenuCommand thông 
    thường nhưng ta thiết kế cho nó invisible, để chỉ khi nào ta muốn Pop-Up nó 
    thì nó mới hiển thị. <BR><BR>Trong VB.NET, Context Menu là một control 
    riêng, nhưng ta edit nó cũng giống như Main Menu. Khi đã thêm một control 
    ContextMenu vào form rồi, mỗi lần ta select nó trong mâm components thì 
    Context Menu hiện ra ở cạnh trên của form giống như Main Menu. Lúc Runtime, 
    khi user right click một control có Context Menu thì ContextMenu sẽ hiển thị 
    ở vị trí đó. <BR><BR>Bạn hãy doubleClick control ContextMenu trong hộp đồ 
    nghề để thêm một Context Menu vào trong form. Kế đó set up các MenuItem như 
    sau:<BR><BR>
    <BLOCKQUOTE><IMG src="Bai 11_files/ContextMenu.gif"></BLOCKQUOTE>Để hiển thị 
    cái <B>Radio button</B> bên trái một MenuItem, bạn phải làm hai chuyện:<BR>
    <OL>
      <LI>Set <B>property Checked</B> của MenuItem thành True để hiển thị một 
      <B>checkmark</B> hay một hình tròn nhỏ (<B>Radio button</B>). 
      <LI>Set <B>property RadioCheck</B> của MenuItem thành True để khi nào nó 
      hiển thị thì có dạng Radio button, thay vì một checkmark. </LI></OL>Nhớ là 
    ta dùng <B>checkmark</B> khi muốn cho user chọn nhiều thứ cùng một lúc, và 
    dùng <B>Radio button</B> khi muốn cho user chỉ chọn một nhiệm ý mà thôi, tức 
    là <B>mutually exclusive</B>. Tuy nhiên, khác với khi edit một nhóm Radio 
    buttons trong một container trên form, VB.NET không cản trở ta cho hai Radio 
    buttons trong một menu cùng hiện ra. Do đó, bạn phải tự quản lý vấn đề 
    mutually exclusive trong code của mình.<BR><BR>Để chỉ định ContextMenu1 
    Pop-up khi user right click Textbox1, bạn chỉ cần set property ContextMenu 
    của Textbox1 thành ContextMenu1 (chọn nó trong cái dropdown list của 
    comboxbox của property ContextMenu trong cửa sổ Properties).<BR><BR>Khi bạn 
    chạy chương trình và right click Textbox1, ContextMenu1 sẽ hiển thị như dưới 
    đây:<BR><BR>
    <BLOCKQUOTE><IMG src="Bai 11_files/WhiteOnBlue.gif"></BLOCKQUOTE>Mã nguồn 
    nằm phía sau các click events của hai MenuItems của ContextMenu1 được liệt 
    kê dưới đây:<BR><BR>
    <TABLE bgColor=#f6f6f6>
      <TBODY>
      <TR>
        <TD><FONT size=3><PRE><FONT color=blue>Private</FONT> <FONT color=blue>Sub</FONT> blackOnWhiteMenuItem_Click( <FONT color=blue>ByVal</FONT> sender <FONT color=blue>As</FONT> System.Object,  _
                                  <FONT color=blue>ByVal</FONT> e <FONT color=blue>As</FONT> System.EventArgs) <FONT color=blue>Handles</FONT> blackOnWhiteMenuItem.Click 
  <FONT color=green>' Change colors of Textbox1</FONT>
   Textbox1.ForeColor = Color.Black 
   Textbox1.BackColor = Color.White 
  <FONT color=green>'Toggle the radio check</FONT>
   blackOnWhiteMenuItem.Checked = <FONT color=blue>True</FONT> 
   WhiteOnBlueMenuItem.Checked = <FONT color=blue>False</FONT> 
<FONT color=blue>End</FONT> <FONT color=blue>Sub</FONT> 

<FONT color=blue>Private</FONT> <FONT color=blue>Sub</FONT> WhiteOnBlueMenuItem_Click( <FONT color=blue>ByVal</FONT> sender <FONT color=blue>As</FONT> System.Object,  _
                                  <FONT color=blue>ByVal</FONT> e <FONT color=blue>As</FONT> System.EventArgs) <FONT color=blue>Handles</FONT> WhiteOnBlueMenuItem.Click 
  <FONT color=green>' Change colors of Textbox1</FONT>
   Textbox1.ForeColor = Color.White 
   Textbox1.BackColor = Color.Blue 
  <FONT color=green>'Toggle the radio check</FONT>
   blackOnWhiteMenuItem.Checked = <FONT color=blue>False</FONT> 
   WhiteOnBlueMenuItem.Checked = <FONT color=blue>True</FONT> 
<FONT color=blue>End</FONT> <FONT color=blue>Sub</FONT> 
</PRE></FONT></TD></TR></TBODY></TABLE>Để ý property Checked của hai 
    MenuItems được coded để hễ cái nầy True thì cái kia phải False, tức là 
    mutually exclusive. Và MenuItem nào có trị số Checked là True thì Radio 
    button hiển thị phía trước nó.<BR>
    <H3><FONT color=blue>Sửa đổi Menus lúc Runtime</FONT></H3>Ta có thể sửa đổi 
    Menu lúc Runtime, chẳng hạn như Context Menu thường có những dạng khác nhau 
    tùy theo trạng thái của một control hay form.<BR><BR>Một thí dụ khác là hiển 
    thị danh sách các files mà chương trình truy cập trong quá khứ. Thông thường 
    ta chứa tên các files ấy trong Registry và khi cần sẽ đọc và load vào 
    Menu.<BR><BR>Dưới đây là code chỉ cách cho thêm một MenuItem vào trong một 
    ContextMenu, và cách clear (xóa) mọi MenuItems. Ta biết rằng ContextMenu có 
    một property là collection của những MenuItems. Do đó muốn thêm một MenuItem 
    thì cần trải qua ba bước:<BR>
    <OL>
      <LI>Instantiate một MenuItem. 
      <LI>Đăng ký Event Handler (ở đây là <B>AddressOf Sub 
      NewMenuItem_Click</B>), mà chương trình sẽ dùng để xử lý Event Click của 
      MenuItem ấy. 
      <LI>Thêm MenuItem ấy vào <B>collection MenuItems</B> của control 
      ContextMenu. </LI></OL>Thêm vào form hai buttons đặt tên là 
    <B>BtnAddMenuItem</B> và <B>BtnClearContextMenu</B>.<BR><BR>
    <TABLE bgColor=#f6f6f6>
      <TBODY>
      <TR>
        <TD><FONT size=3><PRE><FONT color=blue>Private</FONT> <FONT color=blue>Sub</FONT> BtnAddMenuItem_Click( <FONT color=blue>ByVal</FONT> sender <FONT color=blue>As</FONT> System.Object, <FONT color=blue>ByVal</FONT> e <FONT color=blue>As</FONT> System.EventArgs)  _
                                               <FONT color=blue>Handles</FONT> BtnAddMenuItem.Click 
  <FONT color=green>'Add a menu item at the top of ContextMenu1</FONT>
   <FONT color=blue>Dim</FONT> AnewMenuItem <FONT color=blue>As</FONT> MenuItem <FONT color=green>' Declare a MenuItem variable</FONT>
  <FONT color=green>' Create the new menu Item</FONT>
   AnewMenuItem = <FONT color=blue>New</FONT> MenuItem("New Menu Item!") 
  <FONT color=green>' Register EventHandler for Event Click of this new Menu item</FONT>
   AddHandler AnewMenuItem.Click, AddressOf Me.NewMenuItem_Click 
  <FONT color=green>' Add it to the collection MenuItems</FONT>
   ContextMenu1.MenuItems.Add(0, AnewMenuItem) 
<FONT color=blue>End</FONT> <FONT color=blue>Sub</FONT> 

<FONT color=blue>Private</FONT> <FONT color=blue>Sub</FONT> NewMenuItem_Click( <FONT color=blue>ByVal</FONT> sender <FONT color=blue>As</FONT> System.Object, <FONT color=blue>ByVal</FONT> e <FONT color=blue>As</FONT> System.EventArgs) 
   MessageBox.Show("You clicked new Menu Item!") 
<FONT color=blue>End</FONT> <FONT color=blue>Sub</FONT> 

<FONT color=blue>Private</FONT> <FONT color=blue>Sub</FONT> BtnClearContextMenu_Click( <FONT color=blue>ByVal</FONT> sender <FONT color=blue>As</FONT> System.Object, <FONT color=blue>ByVal</FONT> e <FONT color=blue>As</FONT> System.EventArgs)  _
                                               <FONT color=blue>Handles</FONT> BtnClearContextMenu.Click 
  <FONT color=green>' Remove all the menu items from ContextMenu1</FONT>
   ContextMenu1.MenuItems.Clear() 
<FONT color=blue>End</FONT> <FONT color=blue>Sub</FONT> 
</PRE></FONT></TD></TR></TBODY></TABLE>Sau khi bạn click nút <B>Add 
    MenuItem</B>, lúc bạn right click Textbox1, Pop-up Menu sẽ có thêm một 
    MenuItem như sau:<BR><BR>
    <BLOCKQUOTE><IMG src="Bai 11_files/NewMenuItem.gif"></BLOCKQUOTE>Thử click 
    new Menu Item trong ContextMenu1, chương trình sẽ hiển thị thông điệp <B>You 
    clicked new Menu Item!</B>. Bây giờ click nút <B>Clear ContextMenu</B> rồi 
    right click Textbox1. ContextMenu1 đã bị cleared nên sẽ không hiển thị. 
    <H3><FONT color=blue>Duplicating Menus</FONT></H3>Một việc khác ta có thể 
    làm trong lúc Runtime của chương trình là <B>cloning</B> (tạo object song 
    sinh). Thí dụ, ta muốn dùng <B>Edit</B> menu của MainMenu1 làm ContextMenu 
    (giống giống như trong VB6) cho Textbox1. <BR><BR>Để thực hiện việc nầy, ta 
    dùng <B>method CloneMenu()</B>. Dưới đây là code ta dùng để thay thế 
    ContextMenu1 trong chương trình bằng Edit menu của MainMenu1. <BR><BR>
    <TABLE bgColor=#f6f6f6>
      <TBODY>
      <TR>
        <TD><FONT size=3><PRE><FONT color=blue>Private</FONT> <FONT color=blue>Sub</FONT> BtnCloneMenu_Click( <FONT color=blue>ByVal</FONT> sender <FONT color=blue>As</FONT> System.Object, <FONT color=blue>ByVal</FONT> e <FONT color=blue>As</FONT> System.EventArgs)  _
                                                          <FONT color=blue>Handles</FONT> BtnCloneMenu.Click 
  <FONT color=green>' Instantiate a new ContextMenu object</FONT>
   <FONT color=blue>Dim</FONT> newContextMenu <FONT color=blue>As</FONT> <FONT color=blue>New</FONT> ContextMenu() 
  <FONT color=green>' Add a clone copy of EditMenu to this new ContextMenu's collection of MenuItems</FONT>
   newContextMenu.MenuItems.Add(editMenuItem.CloneMenu) 
  <FONT color=green>' Assign this new Context Menu to Textbox1</FONT>
   Textbox1.ContextMenu = newContextMenu 
<FONT color=blue>End</FONT> <FONT color=blue>Sub</FONT> 
</PRE></FONT></TD></TR></TBODY></TABLE>Khởi động chương trình, click nút 
    <B>Clone Menu</B>, rồi right click TextBox1, ContextMenu mới sẽ hiển thị như 
    dưới đây:<BR><BR>
    <BLOCKQUOTE><IMG src="Bai 11_files/CloneMenu.gif"></BLOCKQUOTE><B>Lưu ý:</B> 
    Vì <B>CloneMenu()</B> clone hoàn toàn Object editMenuItem, kể cả các Event 
    Handlers của các SubMenuItems nên ta không cần phải làm thêm gì cả. 
    <BR><BR>Muốn trở lại trạng thái cũ, tức là dùng ContextMenu1 cho Textbox1, 
    ta chỉ cần reassign ContextMenu1 vào property ContextMenu của Textbox1 như 
    sau:<BR><BR>
    <BLOCKQUOTE>
      <TABLE bgColor=#f6f6f6>
        <TBODY>
        <TR>
          <TD><FONT size=3><PRE>Textbox1.ContextMenu = ContextMenu1 
</PRE></FONT></TD></TR></TBODY></TABLE></BLOCKQUOTE><BR><BR>Bạn có thể <A 
    href="http://www.vovisoft.com/dotNET/Bai11/Menu.zip">tải về chương trình 
    Menu nầy</A> tại đây. 
    <H3><FONT color=green>MDI Forms</FONT></H3>Trong VB6 ta tạo một <B>MDI 
    (Multiple Document Interface)</B> form bằng cách set property 
    <B>MDIChild</B> của form ấy thành True. Một form như thế chỉ có thể được 
    dùng làm child form, tức là nó cần một form MDI parent để hiển thị trong ấy. 
    Ngoài ra, mỗi application chỉ có thể có một form MDI parent duy nhất và chỉ 
    trong lúc thiết kế ta mới có thể chỉ định đặc tính của một form là MDIChild. 
    Một form không thể trở thành một MDIChild lúc Runtime.<BR><BR>Trong VB.NET, 
    một form có thể trở thành một MDI child lúc Runtime bằng cách set 
    <B>property MDIParent</B> của form ấy để nhắm vào một form MDI parent. Do 
    đó, một form có thể vừa là MDIchild form, vừa là form bình thường tùy theo 
    hoàn cảnh. Thật ra, ngược với VB6, ta không thể set property MDIParent lúc 
    thiết kế, mà phải làm lúc Runtime.<BR><BR>Giống như VB6, trong VB.NET ta có 
    thể hiển thị nhiều forms MDIChild trong một form MDI parent, khi parent form 
    di chuyển thì mang theo các forms con. Khi hiển thị nhiều child forms, ta có 
    thể dùng <B>property ActiveForm</B> để biết child form nào hiện thời là 
    Active.<BR><BR>Ta thử khởi động một Windows Application mới. Đổi tên Form1 
    thành ParentForm và chỉ định nó làm MDI parent bằng cách set <B>property 
    IsMDIContainer</B> của nó thành True. Kế đó thêm một form và đổi tên nó 
    thành ChildForm. Dưới đây là code để thêm hai child forms vào ParentForm và 
    hiển thị chúng:<BR><BR>
    <TABLE bgColor=#f6f6f6>
      <TBODY>
      <TR>
        <TD><FONT size=3><PRE><FONT color=green>' Declare child forms of type ChildForm</FONT>
<FONT color=blue>Private</FONT> <FONT color=blue>WithEvents</FONT> FirstChild <FONT color=blue>As</FONT> ChildForm 
<FONT color=blue>Private</FONT> <FONT color=blue>WithEvents</FONT> SecondChild <FONT color=blue>As</FONT> ChildForm 

<FONT color=blue>Private</FONT> <FONT color=blue>Sub</FONT> ParentForm_Load( <FONT color=blue>ByVal</FONT> sender <FONT color=blue>As</FONT> System.Object, <FONT color=blue>ByVal</FONT> e <FONT color=blue>As</FONT> System.EventArgs)  _
                                           <FONT color=blue>Handles</FONT> MyBase.Load 
  <FONT color=green>' Instantiate an Object of type Childform</FONT>
   FirstChild = <FONT color=blue>New</FONT> ChildForm() 
  <FONT color=green>' Make this form the MDI Parent of FirstChild</FONT>
   FirstChild.MdiParent = Me 
   FirstChild.Text = "First Child Form" <FONT color=green>' Set Title</FONT>
  <FONT color=green>' Show FirstChild</FONT>
   FirstChild.Show() 

  <FONT color=green>' Instantiate the second Object of type Childform</FONT>
   SecondChild = <FONT color=blue>New</FONT> ChildForm() 
  <FONT color=green>' Make this form the MDI Parent of SecondChild</FONT>
   SecondChild.MdiParent = Me 
   SecondChild.Text = "Second Child Form" <FONT color=green>' Set Title</FONT>
  <FONT color=green>' Show SecondChild</FONT>
   SecondChild.Show() 

<FONT color=blue>End</FONT> <FONT color=blue>Sub</FONT> 

</PRE></FONT></TD></TR></TBODY></TABLE>Để cung cấp một Menu hiển thị danh 
    sách các forms MDIchild của ParentForm, ta thêm control MainMenu vào 
    ParentForm. Kế đó, tạo một MenuItem tên <B>Windows</B> và set <B>property 
    MDIList</B> của nó thành True. Property nầy sẽ khiến danh sách các forms 
    child tự động hiển thị làm những menu items nằm phía dưới Menu Windows. Danh 
    sách nầy tự động cập nhật khi một child form trở thành Active, được thêm 
    vào, hay bị lấy ra.<BR><BR>Parent MDI form có một method tên là 
    <B>LayoutMDI</B> để tự động sắp đặt vị trí các forms child theo kiểu 
    <B>Cascade</B> hay <B>Tile</B> layout. Thêm một MenuItem tên <B>Tile 
    Vertical</B> và nhét mấy hàng code dưới đây vào form để xử lý Event click 
    của nó:<BR><BR>
    <TABLE bgColor=#f6f6f6>
      <TBODY>
      <TR>
        <TD><FONT size=3><PRE><FONT color=blue>Private</FONT> <FONT color=blue>Sub</FONT> tileVerticalMenuItem_Click( <FONT color=blue>ByVal</FONT> sender <FONT color=blue>As</FONT> System.Object, <FONT color=blue>ByVal</FONT> e <FONT color=blue>As</FONT> System.EventArgs)  _
                           <FONT color=blue>Handles</FONT> tileVerticalMenuItem.Click 
   Me.LayoutMdi(System.Windows.Forms.MdiLayout.TileVertical) 
<FONT color=blue>End</FONT> <FONT color=blue>Sub</FONT> 
</PRE></FONT></TD></TR></TBODY></TABLE>Khởi động chương trình, by default 
    hai forms childs được layout kiểu <B>Cascade</B>. Trong Menu Windows có hiển 
    thị title của hai forms child và cho biết <B>Second Child Form</B> là 
    <B>Active</B> form. 
    <BLOCKQUOTE><IMG src="Bai 11_files/MDIForm.gif"></BLOCKQUOTE>Nếu bạn click 
    <B>Tile vertical</B>, hai forms child sẽ được layout kiểu <B>Tile</B> như 
    dưới đây: 
    <BLOCKQUOTE><IMG src="Bai 11_files/Tile.gif"></BLOCKQUOTE><BR><BR>Bạn có thể 
    <A href="http://www.vovisoft.com/dotNET/Bai11/MDIForm.zip">tải về chương 
    trình MDIForm nầy</A> tại đây. <BR><BR>
    <BLOCKQUOTE><A href="http://www.vovisoft.com/"><IMG height=40 
      src="Bai 11_files/homejump.gif" width=40><A>&nbsp;&nbsp;<A 
      href="http://www.vovisoft.com/dotNET/default.asp">Học Microsoft 
      .NET</A><BR><BR></BLOCKQUOTE></FONT><!-- Start of bottom bar for copyright notice etc -->
    <TABLE class=clsNavLinks id=tblFooterLinks cellSpacing=0 cellPadding=0 
    width="100%" border=0>
      <TBODY>
      <TR>
        <TD class=clsRaised width=785 bgColor=#6699cc colSpan=5>
          <P align=center><FONT face=Tahoma color=#ffffff size=1>Vovisoft © 
          2000. All rights reserved.</FONT></P></TD></TR>
      <TR>
        <TD width=256>
          <P align=center><FONT face=Tahoma size=1>&nbsp;&nbsp; Last Updated: <!--webbot 
      bot="Timestamp" S-Type="REGENERATED" S-Format="%d %b %Y" startspan -->17 
          Jan 2002<!--webbot 
      bot="Timestamp" endspan i-checksum="14753" --> </FONT></P></TD>
        <TD width=181><FONT face=Tahoma size=1>&nbsp;</FONT></TD>
        <TD width=258>
          <P align=center><FONT face=Tahoma size=1><A 
          href="mailto:dixon@vovisoft.com">Webmaster</A></FONT></P></TD></TR></TBODY></TABLE><BR></BLOCKQUOTE></BLOCKQUOTE></BODY></HTML>
